<?php
/**
 * Eka Framework 0.3.0
 *
 * @copyright Copyright (c) 2008 Alexey Yu. Chuprina <656b61@gmail.com> (http://php-eka.googlecode.com)
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 *
 * @version $Id$
 */

require_once 'Eka/File.php';

/**
 * Eka_File_Video
 *
 * @package File
 * @subpackage Video
 */
class Eka_File_Video extends Eka_File
{
	const FORMAT_AVI = 1;
	const FORMAT_MPEG = 2;
	const FORMAT_MOV = 3;
	const FORMAT_WMV = 4;
	const FORMAT_FLV = 5;
	const FORMAT_3GP = 6;

	const CONVERT_FORMAT = 'f';
	const CONVERT_SIZE = 's';
	const CONVERT_FRAME_RATE = 'r';
	const CONVERT_AUDIO_RATE = 'ar';
	const CONVERT_AUDIO_BITRATE = 'ab';

	static private $fileExtensions = array(
		self::FORMAT_AVI => 'avi',
		self::FORMAT_MPEG => 'mpg',
		self::FORMAT_MOV => 'mov',
		self::FORMAT_WMV => 'wmv',
		self::FORMAT_FLV => 'flv',
		self::FORMAT_3GP => '3gp'
		);

	static private $ffmpegFormats = array(
		'avi' => self::FORMAT_AVI,
		'mpeg' => self::FORMAT_MPEG,
		'asf' => self::FORMAT_WMV,
		'flv' => self::FORMAT_FLV
		#@todo добавить 3gp и еще остальные варианты
		);

	static public function getFileExtensionByFormat($format)
	{
		if (key_exists($format, self::$fileExtensions)) {
			return self::$fileExtensions[$format];
		}
		return null;
	}

	############################################################################

	protected $type = self::TYPE_VIDEO;

	protected $format = null;
	protected $width = null;
	protected $height = null;
	protected $duration = null;

	public function __construct($file)
	{
		parent::__construct($file);

		$this->updateInfo();
	}

	protected function updateInfo()
	{
		$output = shell_exec(self::$cmdFfmpeg . ' -i ' . escapeshellarg($this->file) . ' 2>&1');
		$info = array();
		$pattern = '`Input #0, (.+),.+Duration: (\d+):(\d+):([\d\.]+),.+Video:.+,.+, (\d+)x(\d+?)`sU';
		if (!preg_match($pattern, $output, $info)) {
			include_once 'Eka/File/Exception.php';
			throw new Eka_File_Exception('The file is not a video');
		}

		if (!key_exists($info[1], self::$ffmpegFormats)) {
			include_once 'Eka/File/Exception.php';
			throw new Eka_File_Exception('Unknown video format');
		}

		$this->format = self::$ffmpegFormats[$info[1]];
		$this->duration = ($info[2] * 3600) + ($info[3] * 60) + ceil($info[4]);
		$this->width = $info[5];
		$this->height = $info[6];
	}

	public function convert(array $params)
	{
		$this->convertTo($this->getFile(), $params);
		$this->updateInfo();
	}

	public function convertTo($file, array $params = array())
	{
		$tempFile = $file;
		if ($file === $this->getFile()) {
			$tempFile = $this->getDirectory() . '/tmp_' . $this->getName();
		}

		$command = self::$cmdFfmpeg . ' -y -i ' . escapeshellarg($this->file);
		foreach ($params as $param => $value) {
			switch ($param) {
				case self::CONVERT_FORMAT:
				case self::CONVERT_SIZE:
				case self::CONVERT_FRAME_RATE:
				case self::CONVERT_AUDIO_RATE:
				case self::CONVERT_AUDIO_BITRATE:
					$command .= ' -' . $param . ' ' . escapeshellarg($value);
					break;
				default:
					break;
			}
		}
		$command .= ' ' . $tempFile . ' 2>&1';
		$output = shell_exec($command);
		$output;
		if ($file !== $tempFile) {
			rename($tempFile, $file);
		}
		#@todo нужна проверки на успешность
		return new Eka_File_Video($file);
	}

	public function createScreenShot($path, $second)
	{
		/* todo
		 * Как быть если такой файл уже есть?
		 * добавить проверку на успешность
		 */
		$command = self::$cmdFfmpeg . ' -y -i ' . $this->file
			. ' -s ' . escapeshellarg($this->width) . 'x' . escapeshellarg($this->height)
			. ' -vcodec mjpeg -vframes 1 -an -ss ' . escapeshellarg($second)
			. ' -f rawvideo ' . escapeshellarg($path) . ' 2>&1';
		shell_exec($command);
		return Eka_File::factory($path);
	}

	public function getWidth()
	{
		return $this->width;
	}

	public function getHeight()
	{
		return $this->height;
	}

	public function getDuration()
	{
		return $this->duration;
	}

	public function getFormat()
	{
		return $this->format;
	}
}


